

/*
 *    Copyright 2010 Tyler Coles
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonemap.math;

/**
 * A utility class for handling units and unit conversions 
 * within this library.
 * 
 * @author Tyler Coles
 */
public enum LengthUnit {
        /**
         * Miles, using the scale factor 0.6213712 miles per kilometer.
         */
        MILE(0.6213712),
        /**
         * Nautical miles, using the scale factor 0.5399568 nautical miles per kilometer.
         */
        NAUTICAL_MILE(0.5399568),
        /**
         * Rods, using the scale factor 0.0050292 rods to the kilometer.
         * Because your car gets forty rods to the hogshead and that's 
         * they way you likes it.
         */
        ROD(0.0050292),
        /**
         * Kilometers, the primary unit.
         */
        KILOMETER(1.0),
        /**
         * Meters, for ease of use.
         */
        METER(1000.0);

        /**
         * The primary length unit. All scale factors are relative
         * to this unit. Any conversion not involving the primary
         * unit will first be converted to this unit, then to 
         * the desired unit.
         */
        public static final LengthUnit PRIMARY = KILOMETER;

        private double scaleFactor;

        LengthUnit(double scaleFactor) {
                this.scaleFactor = scaleFactor;
        }

        /**
         * Convert a value of this unit type to the units specified
         * in the parameters.
         *  
         * @param toUnit the unit to convert to.
         * @param value the value to convert.
         * @return the converted value.
         */
        public double convertTo(LengthUnit toUnit, double value) {
                double _value = value;
                if (this == PRIMARY) {
                        if (toUnit == PRIMARY)
                                return value; // Avoid multiplying by 1.0 needlessly.
                } else {
                        _value = value / this.scaleFactor; // Convert to primary unit.
                }
                return _value * toUnit.scaleFactor; // Convert to destination unit.
        }

        /**
         * Retrieve the scale factor between this unit and the primary 
         * length unit.
         * 
         * @return the scale factor.
         */
        public double getScaleFactor() {
                return scaleFactor;
        }
}
